//
//  KZWaveView.m
//  KZTools_ObjectC
//
//  Created by 朱凯 on 2018/12/17.
//  Copyright © 2018年 zhukai. All rights reserved.
//

#import "KZWaveView.h"

@implementation KZWaveView
{
    // 波纹数组
    NSMutableArray<__kindof CAShapeLayer *> *_waveLayers;
    // 定时器
    NSTimer *_timer;
    // 记录每个波纹的x偏移量
    NSMutableArray *_offsetXs;
    // 记录每个波纹的y偏移量
    NSMutableArray *_offsetYs;
    // 记录每个波纹的动态y偏移量
    NSMutableArray *_dynamics;
    // 记录每个波纹的动态偏移量系数（如果动态偏移量大于预设值或小于负的预设值，则系数反转）
    NSMutableArray *_cs;
}
- (instancetype)init {
    if (self = [super init]) {
        
        _waves = 1;
    }
    return self;
}
- (void)layoutSubviews {
    
    if (_timer) {
        return;
    }
    
    [super layoutSubviews];
    
    // 适配波纹的数值数组和波数
    _colors =           [self checkWaveValues:_colors baseValue:UIColor.blueColor];
    _amplitudes =       [self checkWaveValues:_amplitudes baseValue:@10];
    _cycles =           [self checkWaveValues:_cycles baseValue:@(self.width)];
    _speeds =           [self checkWaveValues:_speeds baseValue:@1];
    _initialPhases =    [self checkWaveValues:_initialPhases baseValue:@0];
    _allowDynamics =    [self checkWaveValues:_allowDynamics baseValue:@NO];
    _dynamicValues =    [self checkWaveValues:_dynamicValues baseValue:@0];
    _riseAnimateds =    [self checkWaveValues:_riseAnimateds baseValue:@YES];
    _risePercents =     [self checkWaveValues:_risePercents baseValue:@0.6];
    
    _cs = [NSMutableArray new];
    _offsetXs = [NSMutableArray new];
    _offsetYs = [NSMutableArray new];
    _dynamics = [NSMutableArray new];
    _waveLayers = [NSMutableArray new];
    for (int i = 0; i < _waves; i ++) {
        
        [_dynamics addObject:@0];
        [_cs addObject:@1];
        [_offsetXs addObject:@0];
        [_offsetYs addObject:@(0)];
        
        CAShapeLayer *waveLayer = [CAShapeLayer layer];
        waveLayer.fillColor = _colors[i].CGColor;
        waveLayer.strokeColor = UIColor.clearColor.CGColor;
        [self.layer addSublayer:waveLayer];
        
        [_waveLayers addObject:waveLayer];
    }
    
    if (!_timer) {
        _timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updatePath) userInfo:nil repeats:true];
        [[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
    }
}
- (NSArray *)checkWaveValues:(NSArray *)array baseValue:(id)baseValue {
    if (array.count != _waves) {
        if (array == nil) {
            array = @[];
        }
        NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:array];
        if (temp.count > _waves) {
            temp = [temp subarrayWithRange:NSMakeRange(0, _waves)].mutableCopy;
        } else {
            for (int i = (int)array.count; i <_waves; i ++) {
                [temp addObject:baseValue];
            }
        }
        return temp.copy;
    } else {
        return array;
    }
}
- (void)updatePath {

    for (int i = 0; i < _waves; i ++) {
        CGFloat amplitude = _amplitudes[i].doubleValue;
        CGFloat speed = _speeds[i].doubleValue;
        CGFloat cycle = _cycles[i].doubleValue;
        CGFloat initialPhase = _initialPhases[i].doubleValue;
        Boolean allowDynamic = _allowDynamics[i].boolValue;
        CGFloat dynamicValue = _dynamicValues[i].doubleValue;
        Boolean riseAnimated = _riseAnimateds[i].boolValue;
        CGFloat risePercent = _risePercents[i].doubleValue;

        
        CGFloat offsetX = [_offsetXs[i] doubleValue];
        offsetX += 1 * speed;
        _offsetXs[i] = @(offsetX);
        CGFloat offsetY = 0;
        if (riseAnimated) {
            offsetY = [_offsetYs[i] doubleValue];
            offsetY += 1;
            offsetY = MIN(offsetY, self.height * risePercent);
            _offsetYs[i] = @(offsetY);
        } else {
            offsetY = self.height * risePercent;
        }
        CGFloat dynamic = 0;
        CGFloat c = 1;
        if (allowDynamic) {
            dynamic = [_dynamics[i] doubleValue];
            c = [_cs[i] intValue];
            if (floor(dynamic) == floor(dynamicValue) || floor(dynamic) == -floor(dynamicValue)) {
                c *= -1;
            }
            dynamic += c * 0.1;
            _dynamics[i] = @(dynamic);
            _cs[i] = @(c);
        }
        
        CAShapeLayer *waveLayer = _waveLayers[i];
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(0, self.height)];
        for (int x = 0; x < self.width; x ++) {
            CGFloat y = (amplitude + dynamic) * sin((2 * M_PI / cycle * (x - offsetX) + initialPhase)) + self.height - offsetY;

            [path addLineToPoint:CGPointMake(x, y)];
        }
        [path addLineToPoint:CGPointMake(self.width, self.height)];
        [path closePath];
        waveLayer.path = path.CGPath;
    }
}
- (void)free {
    
    [_timer invalidate];
    _timer = nil;
}

@end
